package peer.gui;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedList;
import java.util.Random;

import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SpringLayout;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;

import peer.NetworkManager.NetworkManager;
import peer.SharingManager.SharingManager;

import common.Packet;
import common.Util;


public class SearchPanel extends JPanel implements ActionListener, ListSelectionListener
{
	JTextField searchField;
	JTable resultTable;
	JList searchList;
	DefaultListModel searchesListModel;
	LinkedList<SearchResultModel> searchResults = new LinkedList<SearchResultModel>();
	
	PeerGUI gui;
	
	public SearchPanel(PeerGUI gui)
	{
		this.gui = gui;
		//set the layout
		SpringLayout layout = new SpringLayout();
		setLayout(layout);
		
		//create, add and position the text entry field and the buttons on the top of the pane
		searchField = new JTextField(20);
		JButton searchButton = new JButton("Search");
		searchButton.setActionCommand("search");
		searchButton.addActionListener(this);
		JButton downloadButton = new JButton("Download selected");
		downloadButton.setActionCommand("download");
		downloadButton.addActionListener(this);
		
		add(searchField);
		add(searchButton);
		add(downloadButton);
		
		layout.putConstraint(SpringLayout.WEST, searchField, 5, SpringLayout.WEST, this);
		layout.putConstraint(SpringLayout.NORTH, searchField, 5, SpringLayout.NORTH, this);
		layout.putConstraint(SpringLayout.WEST, searchButton, 5, SpringLayout.EAST, searchField);
		layout.putConstraint(SpringLayout.NORTH, searchButton, 5, SpringLayout.NORTH, this);
		layout.putConstraint(SpringLayout.WEST, downloadButton, 5, SpringLayout.EAST, searchButton);
		layout.putConstraint(SpringLayout.NORTH, downloadButton, 5, SpringLayout.NORTH, this);
		layout.putConstraint(SpringLayout.EAST, this, 5, SpringLayout.EAST, downloadButton);
		
		//create, add and position the list of searches on the left of the pane
		searchesListModel = new DefaultListModel();
		searchList = new JList(searchesListModel);
		searchList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		searchList.addListSelectionListener(this);
		JScrollPane searchesScrollPane = new JScrollPane(searchList);
		searchesScrollPane.setPreferredSize(new Dimension(150, 500));
		add(searchesScrollPane);
		
		layout.putConstraint(SpringLayout.WEST, searchesScrollPane, 5, SpringLayout.WEST, this);
		layout.putConstraint(SpringLayout.NORTH, searchesScrollPane, 5, SpringLayout.SOUTH, searchButton);
		layout.putConstraint(SpringLayout.SOUTH, searchesScrollPane, -5, SpringLayout.SOUTH, this);
		
		//create the table
		SearchResultModel initialResultModel = new SearchResultModel();
		resultTable = new JTable(initialResultModel);
		initialResultModel.addTableModelListener(resultTable);
		resultTable.getColumn("Filename").setPreferredWidth(200);
		resultTable.getColumn("Peers").setPreferredWidth(50);
		//resultTable.getColumn("Hashcode").setPreferredWidth(120);
		
		JScrollPane resultPane = new JScrollPane(resultTable); 
		add(resultPane);
		
		layout.putConstraint(SpringLayout.WEST, resultPane, 5, SpringLayout.EAST, searchesScrollPane);
		layout.putConstraint(SpringLayout.NORTH, resultPane, 5, SpringLayout.SOUTH, searchButton);
		layout.putConstraint(SpringLayout.EAST, resultPane, 0, SpringLayout.EAST, downloadButton);
		layout.putConstraint(SpringLayout.SOUTH, this, 5, SpringLayout.SOUTH, resultPane);
	}

	public void actionPerformed(ActionEvent e)
	{
		if(e.getActionCommand().equals("search"))
		{
			try
			{
				//create a new result model to put the search results into
				SearchResultModel newModel = new SearchResultModel(searchField.getText());
				searchResults.add(newModel);
				//add a new entry into the list
				searchesListModel.addElement(searchField.getText());
				//and now call the search function...
				Packet p = new Packet(Packet.Type.search);
				p.addHeader("die_in", "11");
				p.addHeader("for", InetAddress.getLocalHost().getHostAddress() + ":" + NetworkManager.instance().getQuerySocket().getLocalPort());
				p.addHeader("search_id", Long.toString((new Random(System.nanoTime())).nextLong()));
				p.addHeader("query", searchField.getText());
				SharingManager.instance().propogateSearch(p, null);
				
				//TODO: make this call the search function, and delete the test code following this
				/*String name = searchField.getText();
				Random r = new Random(System.nanoTime());
				MessageDigest md = null;
				try{md = MessageDigest.getInstance("MD5");} catch (NoSuchAlgorithmException e1){}
				md.update(name.getBytes());
				long size = (long) Math.pow(2, r.nextInt(50));
				size *= r.nextDouble();
				newModel.addResult("search: " + name, size, Util.convertByteArrayHashcodeToHex(md.digest()));
				searchList.setSelectedIndex(searchesListModel.getSize() - 1);*/
			} catch (UnknownHostException ex)
			{
				System.out.println("unable to find IP address of this host");
				ex.printStackTrace();
			}
		}
		else if(e.getActionCommand().equals("download"))
		{
			if(resultTable.getSelectedRow() >= 0)
			{
				//would normally call the download function...
				//TODO: this; you may want to use the following variables
				String name = ((SearchResultModel) resultTable.getModel()).getNameAt(resultTable.getSelectedRow());
				long size = ((SearchResultModel) resultTable.getModel()).getSizeAt(resultTable.getSelectedRow());
				int peers = ((SearchResultModel) resultTable.getModel()).getPeersAt(resultTable.getSelectedRow());
				String hashcode = ((SearchResultModel) resultTable.getModel()).getHashcodeAt(resultTable.getSelectedRow());
				//((SearchResultModel) resultTable.getModel()).addResult("download \"" + name + "\"", size, hashcode);
				
				gui.setDownloadFile(name, peers, size, hashcode);
			}
			else
			{
				//no file (row) selected
				
			}
		}
	}

	public void valueChanged(ListSelectionEvent e)
	{
		//remove the listener from from what is the currently shown table 
		resultTable.getModel().removeTableModelListener(resultTable);
		//make the selected search show its table
		resultTable.setModel(searchResults.get(searchList.getSelectedIndex()));
		//and add a listener to the newly displayed table
		resultTable.getModel().addTableModelListener(resultTable);
		
	}

	public void addNewSeach(String query)
	{
		searchesListModel.addElement(query);
	}

	public void addSearchResult(String query, String filename, long size, String hashcode)
	{
		for (SearchResultModel s : searchResults)
		{
			if(s.getQuery().equals(query))
			{
				s.addResult(filename, size, hashcode);
			}
		}
		
	}
}
